package
{
	import com.greensock.TweenLite;
	import com.greensock.easing.Bounce;
	import com.greensock.easing.Elastic;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;

	public class Mall implements IPersistable
	{
		public var display:Sprite = new Sprite();
		public var expansionsPurchased:int = 0;
		public var overlay:Sprite = new Sprite();
		private var allowableLayer:Sprite = new Sprite();
		private var scaffoldsLayer:Sprite = new Sprite();		
		private var mallStoresLayer:Sprite = new Sprite();
		private var mallShoppersLayer:Sprite = new Sprite();
		private var escalatorsLayer:Sprite = new Sprite();
		
		private var m_scaffolds:Vector.<Scaffold> = new Vector.<Scaffold>;
		private var m_storeIdCounter:int = 0;		
		public var id:String;
		public var maintenancePercent:Number;
		public var stores:Vector.<Store> = new Vector.<Store>;		
		public var m_allowableRectangle:Rectangle;
		
		private var m_menusBeingShown:Vector.<Sprite> = new Vector.<Sprite>;
		
		private var m_shoppersInMall:Vector.<GameObject> = new Vector.<GameObject>;
		
		private var m_timeBetweenEnters:int = 1500;
		private var m_lastTimeSomeoneEntered:int;
		
		private var m_fillStockTime:int = Game.config.restockTime;
		private var m_lastFillStockTime:int;
		public var escalators:Vector.<Escalator> = new Vector.<Escalator>;
		
		public var maintenanceDepletionRate:int = 86400/6;
		
		public var maintenance:Number = 100;
		
		public function Mall()
		{
			display.addChild(allowableLayer);
			display.addChild(scaffoldsLayer);
			display.addChild(mallStoresLayer);
			display.addChild(mallShoppersLayer);	
			display.addChild(escalatorsLayer);
			//hideAllowableArea();
			m_lastMaintenancePaid = getTimer();
		
		}
		
		private var m_lastMaintenancePaid:int;
		
		public function step(delta:int):void{
			if(getTimeUntilRestock() <= 0){
				restock();
			}
			var curTimer:int = getTimer();
			var delta:int = (curTimer - m_lastMaintenancePaid) / 1000;
			var maintenanceRemoval:Number = 100 * delta / maintenanceDepletionRate;
			maintenance = 100 - maintenanceRemoval;
		}
		
		public function expand():void{
			expansionsPurchased++;
			m_allowableRectangle = new Rectangle(m_allowableRectangle.x - Game.config.baseStoreWidth, m_allowableRectangle.y, m_allowableRectangle.width + Game.config.baseStoreWidth*2, m_allowableRectangle.height + 1);
			this.allowableRectangle = m_allowableRectangle;
			//var scale:Number = (allowableLayer.width - Game.PPS*2)/allowableLayer.width
			allowableLayer.scaleX = .6;
			allowableLayer.scaleY = .6;
			TweenLite.to(allowableLayer, 1, {scaleX: 1, scaleY: 1, ease: Elastic.easeInOut});
			
			var esc:Escalator;
			esc = new Escalator();
			esc.location = new Point(-Game.config.baseStoreWidth,allowableRectangle.height-2);
			escalators.push(esc);
			escalatorsLayer.addChild(esc.display);
			Util.bounceDown(esc.display);
			esc = new Escalator();
			esc.location = new Point(1,allowableRectangle.height-2);
			escalators.push(esc);
			escalatorsLayer.addChild(esc.display);
			Util.bounceDown(esc.display);
			//Util.scale(allowableLayer, .8, 1, 1, 1, 1, Elastic.easeInOut);
		}
		
		
		
		public function getCostForNextExpansion():Number{
			var area:Number = (m_allowableRectangle.height+1)*(m_allowableRectangle.width+Game.config.baseStoreWidth);
			return area*Game.config.expansionCostUnit;			
		}
		
		public function getTimeUntilRestock():int{
			return m_fillStockTime - (getTimer() - m_lastFillStockTime);
		}
		
		public function restock():void{
			m_lastFillStockTime = getTimer();
			var i:int, l:int;
			for(i = 0, l = stores.length; i < l; i++){
				stores[i].currentStock = stores[i].maxStock;
				stores[i].hideOutOfStock();
			}
		}
		
		public function enterMall(shopper:GameObject):void{
			m_shoppersInMall.push(shopper);
			mallShoppersLayer.addChild(shopper.display);
			m_lastTimeSomeoneEntered = getTimer();
			
		}
		
		public function lettingShoppersIn():Boolean{
			var curTime:int = getTimer();
			var deltaTimeSinceEntrance:int = curTime - m_lastTimeSomeoneEntered;
			if(deltaTimeSinceEntrance > m_timeBetweenEnters){
				return true;
			} else {
				return false;
			}
		}
		
		public function leaveMall(shopper:GameObject):void{
			m_shoppersInMall.splice(m_shoppersInMall.indexOf(shopper),1);
			TweenLite.to(shopper.display, 1, {alpha: 0,
				onComplete: function():void{
					shopper.display.visible = false;
					mallShoppersLayer.removeChild(shopper.display);
				}
			});			
		}
		
		public function showMenu(store:Store):void{
			closeAllMenus();
			
			var menu:Sprite = store.getMenu();
			m_openMenus.push(menu);
			overlay.addChild(menu);
			menu.visible = true;
			menu.x = store.display.x - menu.width/2;
			menu.y = store.display.y - menu.height - Game.PADDING;
			menu.alpha = 0;
			TweenLite.to(menu, .25, {alpha:1, x: store.display.x});
		}
		
		public function closeAllMenus():void{
			var i:int, l:int;
			for(i = 0, l = stores.length; i < l; i++){
				if(m_openMenus.indexOf(stores[i].getMenu()) != -1){
					hideMenu(stores[i]);
				}
			}
		}
		
		private var m_openMenus:Vector.<Sprite> = new Vector.<Sprite>;
		
		public function hideMenu(store:Store):void{
			var menu:Sprite = store.getMenu();
			menu.visible = true;
			menu.alpha = 1;
			TweenLite.to(menu, .25, {alpha:0, x: store.display.x + menu.width/2,
				onComplete: function():void{
					m_openMenus.splice(m_openMenus.indexOf(menu), 1);
					menu.visible = false;
					menu.parent.removeChild(menu);
					
				}
			});
		}	
		
		public function toggleMenu(store:Store):void{
			if(store.getMenu().parent != null){
				hideMenu(store);
			} else {
				showMenu(store);
			}
		}
		
		
		public function get allowableRectangle():Rectangle{
			return m_allowableRectangle;
		}
		
		public function set allowableRectangle(allowableRectangle:Rectangle):void{
			m_allowableRectangle = allowableRectangle;
			Util.removeChildren(allowableLayer);
			
			var allowableBackdrop:Sprite = Util.getRectSprite(m_allowableRectangle.width*Game.PPS, m_allowableRectangle.height*Game.PPS,0,.5);
			allowableBackdrop.y = -m_allowableRectangle.height * Game.PPS;
			allowableBackdrop.x = allowableRectangle.x * Game.PPS;
			allowableLayer.addChild(allowableBackdrop);
		}
		
		public function showAllowableArea():void{
			allowableLayer.visible = true;
		}
		
		public function hideAllowableArea():void{
			allowableLayer.visible = false;
		}
		
		public function previewStore(store:Store):void{
			mallStoresLayer.addChild(store.display);
		}
		
		public function pickStore(mousePosition:Point):Store{
			var i:int, length:int;
			if(isInMallArea(mousePosition)){
				for(i = 0, length = stores.length; i < length; i++){
					if(stores[i].hitTestPoint(mousePosition)){
						return stores[i];
					}
				}
			}
			
			return null;
		}
		
		public function isInMallArea(mousePosition:Point):Boolean{
			return display.hitTestPoint(mousePosition.x, mousePosition.y)			
		}		
		
		public function getStoreById(storeId:int):Store{
			for(var i:int = 0, l:int = stores.length; i < l; i++){
				if(stores[i]['id'] == storeId){
					return stores[i];
				}
			}
			
			throw new Error("store id" + storeId + " not found");			
		}
				
		
		public function initializeObjectIds(savedObject:Object):void{
			var i:int, l:int;
			for(i= 0, l = savedObject['stores'].length; i < l; i++){
				var store:Store = new Store();
				store.id = savedObject['stores'][i]['id'];
				stores.push(store);
			}			
		}
		
		
		private function initializeStores(stores:Array):void{
			for(var i:int = 0, l:int = stores.length; i < l; i++){
				var store:Store = getStoreById(stores[i]['id']);
				store.loadSavedObject(stores[i]);
				mallStoresLayer.addChild(store.display);
			}
			
		}
		
		
		private function autoPlaceAStore():void{
			var nextStoreLocation:Point;
			var store:Store = new Store();
			store.init('tools');
			
			if(stores.length){
				if(stores[length-1].location.x > 8){
					nextStoreLocation = new Point(0, stores[length-1].location.y + 1);
				} else {
					nextStoreLocation = new Point(stores[length-1].location.x + 2, stores[length-1].location.y);	
				}
				
			} else {
				nextStoreLocation = new Point(-4,0);
			}
			
			store.location = nextStoreLocation.clone();
			addStore(store);
			var locationY:int = store.display.y;
			
			store.display.alpha = 0;
			store.display.y = locationY - 500;
			TweenLite.to(store.display, 1, {y: locationY, alpha: 1, ease: Bounce.easeOut});
		}
		
		
		private function addStore(store:Store):void{
			store.id = m_storeIdCounter++;
			stores.push(store);
			mallStoresLayer.addChild(store.display);
		}
		
		private function createStore(owner:Player, location:Point):void{
			var store:Store = new Store();
			store.init(Util.getRandomStoreNoun());
			store.owner = owner;
			store.location = location.clone();
			stores.push(store);	
		}
		
		
		public function buyScaffold(pos:Point):void{
			var scaffold:Scaffold = new Scaffold();
			scaffoldsLayer.addChild(scaffold.display);
			scaffold.display.alpha = 0;
			scaffold.display.y = pos.y - 500;
			scaffold.display.x = pos.x;
			TweenLite.to(scaffold.display, 1, {y: pos.y, alpha: 1, ease: Bounce.easeOut});
			m_scaffolds.push(scaffold);
		}
		
		public function stage2me(stagePoint:Point):Point{
			var mallPoint:Point = stagePoint.subtract(new Point(display.x + display.parent.x, display.y + display.parent.y));
			return new Point(mallPoint.x/Game.PPS, -mallPoint.y/Game.PPS);
		}		
		
		public function buyStore(storeName:String, location:Point, owner:Player):void{
			var store:Store = new Store();
			store.init(storeName);
			store.currentStock = store.maxStock;
			store.showStockInfo();
			store.location = location.clone();
			store.owner = owner;
			store.mall = this;
			
			owner.cash -= store.value;
			addStore(store);
			
			
			Util.bounceDown(store.display);
		}
		public function moveStore(store:Store, location:Point):void{
			var startDisplay:Point = new Point(store.display.x, store.display.y);
			store.location = location;
			var endDisplay:Point = new Point(store.display.x, store.display.y);
			
			store.display.x = startDisplay.x;
			store.display.y = startDisplay.y;
			
			TweenLite.to(store.display, .5, {alpha: 0, y: store.display.y - 500, 
				onComplete: function():void{
					store.display.x = endDisplay.x;
					store.display.y = endDisplay.y;
					Util.bounceDown(store.display);
				}
			});
		}
		
		/*********************************************
		 * IPersistable
		 *****************************************/
		public function getSaveObject():Object{
			var saveObj:Object = new Object();
			saveObj['id'] = id;
			saveObj['storeCounter'] = m_storeIdCounter;
			for each(var store:Store in stores){
				saveObj['stores'].push(store.getSaveObject());
			}
			
			return saveObj;
		}
		
		
		public function loadSavedObject(savedObject:Object):void{
			initializeStores(savedObject['stores']);
			m_storeIdCounter = savedObject['storeIdCounter'];
		}		
	}
}